﻿using CreateCodeByDatabase.Bll;
using CreateCodeByDatabase.Model;
using CreateCodeByDatabase.Model.MS_XTPT;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CreateCodeByDatabase
{
    public partial class Form1 : Form
    {
        IOperate operate { get; set; }
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            operate = IOperate.GetOperate();
            lblNoticeInfo.Text = "提示信息";
            dropConnections.Items.Clear();
            foreach (ConnectionStringSettings item in ConfigurationManager.ConnectionStrings)
            {
                dropConnections.Items.Add(item.Name);
            }
        }
        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnQuery_Click(object sender, EventArgs e)
        {
            //txtTableName.Text = "t_hj_";
            IEnumerable<TableInfo> entityList = operate.QueryTableList(txtTableName.Text.Trim());
            gridMain.DataSource = entityList;

            //System.Text.StringBuilder sql = new StringBuilder();
            //sql.AppendLine("begin");
            //foreach (var item in entityList)
            //{
            //    sql.AppendLine($"delete from {item.TableName};");
            //}
            //sql.AppendLine("end;");
            //string sqlInfo = sql.ToString();
            lblNoticeInfo.Text = "查询成功";
        }
        /// <summary>
        /// 生成文件操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreateFile_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
            folderBrowserDialog1.ShowNewFolderButton = true;
            folderBrowserDialog1.Description = "请选择文件保存路径";
            if (folderBrowserDialog1.ShowDialog() != DialogResult.OK)
                return;
            //new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(StartCreatFile)).Start();   
            new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(StartCreatFile)).Start(folderBrowserDialog1.SelectedPath);
        }
        /// <summary>
        /// 开始生成文件
        /// </summary>
        private void StartCreatFile(object tempPath)
        {
            try
            {
                string saveFilePath = tempPath.ToString();
                IEnumerable<TableInfo> dataList = gridMain.DataSource as IEnumerable<TableInfo>;
                var tempDataList = dataList.Where(Item => Item.IsChoice);
                IEnumerable<string> tableNameList = tempDataList.Select(Item => Item.TableName);
                Dictionary<string, string> tableNameCommentDic = tempDataList.ToDictionary(Item => Item.TableName, Text => Text.Comment);
                if (tableNameList.Count() < 1)
                {
                    MessageBox.Show("请选择表");
                    return;
                }
                Dictionary<string, List<ColumnInfo>> resultDic = GetTableColumnDic(tableNameList);
                CreateFile(resultDic, tableNameCommentDic, saveFilePath);
            }
            catch (Exception ex)
            {
                Log.WriteLog(ex);
                WriteNotice(lblNoticeInfo, ex.Message);
            }
        }
        /// <summary>
        /// 获取指定表列信息字典
        /// </summary>
        /// <param name="tableNameList"></param>
        /// <returns>格式:[表名,{列信息}]</returns>
        private Dictionary<string,List<ColumnInfo>> GetTableColumnDic(IEnumerable<string> tableNameList)
        {
            Dictionary<string, List<ColumnInfo>> resultDic = new Dictionary<string, List<ColumnInfo>>();
            IEnumerable<ColumnInfo> entitList = operate.GetTableColumnList(tableNameList);
            foreach (var item in entitList)
            {
                if (resultDic.ContainsKey(item.TableName))
                    resultDic[item.TableName].Add(item);
                else
                    resultDic.Add(item.TableName,new List<ColumnInfo>() { item});
            }
            return resultDic;
        }
        private void CreateFile(Dictionary<string, List<ColumnInfo>> resultDic, Dictionary<string, string> tableNameCommentDic, string saveFilePath)
        {
            string className = null;
            string DefaultNameSpace = txtDefaultNameSpace.Text.Trim();
            if (string.IsNullOrWhiteSpace(DefaultNameSpace))
                DefaultNameSpace = "Model";
            StringBuilder fileContent = new StringBuilder();
            StringBuilder addSqlBuilder = new StringBuilder();
            StringBuilder addSqlBuilder2 = new StringBuilder();
            StringBuilder editSqlBuilder = new StringBuilder();
            int tempCount = 0;
            //string excelPath = @"D:\work\source\gysxt\01.MSPRJ\MSDOC\数据库设计\申洲供应商协同管理平台-棉纱采购订单数据与接口列表.xlsx";
            Dictionary<string, List<TableComment>> tableCommentDic = null;// ExcelHelper_MS_XTPT.GetFieldComment(excelPath);

            dProgressBarUpdate dp = new dProgressBarUpdate(ProgressBarUpdate);
            foreach (var item in resultDic)
            {
                #region 处理类名称
                className = "";
                //string[] InfoArray = item.Key.Split('_');
                //for (int i = 1; i < InfoArray.Length; i++)
                //{
                //    if (string.IsNullOrWhiteSpace(InfoArray[i]))
                //        continue;
                //    className += InfoArray[i][0].ToString().ToUpper() + InfoArray[i].Substring(1).ToLower();
                //}
                className = item.Key.ToUpper();//+= InfoArray[InfoArray.Length - 2].ToUpper() + "_" + InfoArray[InfoArray.Length - 1].ToUpper();
                #endregion

                fileContent.Clear();
                if (!tableNameCommentDic.ContainsKey(item.Key))
                    continue;
                addSqlBuilder.Append("INSERT INTO "+ item.Key + " (");
                addSqlBuilder2.Append(") VALUES (REPLACE(NEWID(),'-',''),");
                editSqlBuilder.Append("UPDATE " + item.Key + " SET ");
                fileContent.AppendLine("using System;");
                fileContent.AppendLine("using System.Collections.Generic;");
                //fileContent.AppendLine("using System.Runtime.Serialization;");
                //fileContent.AppendLine("using WebService.Common.Model;");
                fileContent.AppendLine();
                fileContent.AppendLine("namespace " + DefaultNameSpace);
                fileContent.AppendLine("{");
                fileContent.AppendLine("\t/// <summary>");
                fileContent.AppendLine("\t///  " + tableNameCommentDic[item.Key]);
                fileContent.AppendLine("\t/// </summary>");
                //fileContent.AppendLine("\t[DataContract]");
                //fileContent.AppendLine("\t[DataContract]");
                //fileContent.AppendLine("\t[Table(Name = \""+ item.Key + "\")]");
                fileContent.AppendLine("\tpublic class " + className);
                fileContent.AppendLine("\t{");
                foreach (var column in item.Value)
                {
                    string filedDataType = null;
                    if(IOperate.ConnectionType == enumConnectionType.Oracle)
                        filedDataType = GetFieldDataType_Ora(column.DataType);
                    else if(IOperate.ConnectionType == enumConnectionType.SqlServer)
                        filedDataType = GetFieldDataType_Sql(column.DataType);
                    else if (IOperate.ConnectionType == enumConnectionType.MySql)
                        filedDataType = GetFieldDataType_MySql(column.DataType.ToUpper());
                    if (!string.IsNullOrWhiteSpace(column.Comment))
                    {
                        fileContent.AppendLine("\t\t/// <summary>");
                        fileContent.AppendLine("\t\t///  " + column.Comment);
                        fileContent.AppendLine("\t\t/// </summary>");
                    }
                    //string tempComment = null;
                    string tempColumnCode = ColumnNameHandle(column.ColumnName);
                    //if (tableCommentDic != null && tableCommentDic.ContainsKey(className))
                    //{
                    //    var TableComment = tableCommentDic[className].FirstOrDefault(d=>d.FieldCode == tempColumnCode);
                    //    if(TableComment != null)
                    //    {
                    //        tempComment = TableComment.FieldName;
                    //        if (!string.IsNullOrWhiteSpace(TableComment.Comment))
                    //            tempComment = tempComment + " " + TableComment.Comment;
                    //    }
                    //}
                    //if( !string.IsNullOrWhiteSpace(tempComment) )
                    //{
                    //    tempComment = tempComment.Replace("\r\n", "\r\n\t\t///  ");
                    //    fileContent.AppendLine("\t\t/// <summary>");
                    //    fileContent.AppendLine("\t\t///  " + tempComment);
                    //    fileContent.AppendLine("\t\t/// </summary>");
                    //}

                    //fileContent.AppendLine("\t\t[DataMember]");
                    fileContent.AppendLine("\t\tpublic " + filedDataType + " " + tempColumnCode + " { get; set; }");
                    addSqlBuilder.Append(column.ColumnName + ",");
                    if(filedDataType == "DateTime?")
                        addSqlBuilder2.Append("getdate(),");
                    else
                        addSqlBuilder2.Append("@" + ColumnNameHandle(column.ColumnName) + ",");
                    if (filedDataType == "DateTime?")
                        editSqlBuilder.Append(column.ColumnName + "= getdate(),");
                    else
                        editSqlBuilder.Append(column.ColumnName + "= @" + ColumnNameHandle(column.ColumnName) + ",");


                }
                fileContent.AppendLine("\t}");
                fileContent.AppendLine("}");
                
                string filePath = Path.Combine(saveFilePath, className + ".cs");
                File.WriteAllText(filePath, fileContent.ToString(), Encoding.UTF8);
                tempCount++;
                ProgressBarUpdate(resultDic.Count, tempCount);

                addSqlBuilder = addSqlBuilder.Remove(addSqlBuilder.Length - 1, 1);
                addSqlBuilder2 = addSqlBuilder2.Remove(addSqlBuilder2.Length - 1, 1);
                addSqlBuilder2.Append(")");
                addSqlBuilder.Append(addSqlBuilder2.ToString());
                editSqlBuilder = editSqlBuilder.Remove(editSqlBuilder.Length - 1, 1);
            }
            WriteNotice(lblNoticeInfo, "操作成功");
            //MessageBox.Show("操作成功");

            ShowCreateSql aimForm = new ShowCreateSql(addSqlBuilder.ToString(), editSqlBuilder.ToString());
            aimForm.ShowDialog();
        }
        /// <summary>
        /// 获取对应字段数据类型
        /// </summary>
        /// <param name="dataType">oracle数据库列数据类型</param>
        /// <returns></returns>
        private string GetFieldDataType_Ora(string dataType)
        {
            string filedDataType = null;
            switch (dataType)
            {
                case enumDataType.CHAR:
                case enumDataType.CLOB:
                case enumDataType.LONG:
                case enumDataType.NCHAR:
                case enumDataType.NVARCHAR2:
                case enumDataType.VARCHAR2:
                    filedDataType = "string";
                    break;
                case enumDataType.DATE:
                case enumDataType.TIMESTAMP:
                    filedDataType = "DateTime?";
                    break;
                case enumDataType.INT:
                    filedDataType = "int?";
                    break;
                case enumDataType.FLOAT:
                case enumDataType.DOUBLE:
                case enumDataType.NUMBER:
                    filedDataType = "decimal?";
                    break;
                case enumDataType.RAW:
                    filedDataType = "byte[]";
                    break;
                default:
                    filedDataType = "string";
                    break;
            }
            return filedDataType;
        }
        private string GetFieldDataType_Sql(string dataType)
        {
            string filedDataType = null;
            switch (dataType)
            {
                case enumDataType.CHAR:
                case enumDataType.CLOB:
                case enumDataType.LONG:
                case enumDataType.NCHAR:
                case enumDataType.NVARCHAR:
                case enumDataType.VARCHAR:
                    filedDataType = "string";
                    break;
                case enumDataType.DATE:
                case enumDataType.DATETIME:
                case enumDataType.TIMESTAMP:
                    filedDataType = "DateTime?";
                    break;
                case enumDataType.INT:
                    filedDataType = "int?";
                    break;
                case enumDataType.FLOAT:
                case enumDataType.DOUBLE:
                case enumDataType.NUMBER:
                case enumDataType.DECIMAL:
                    filedDataType = "decimal?";
                    break;
                case enumDataType.RAW:
                    filedDataType = "byte[]";
                    break;
                default:
                    filedDataType = "string";
                    break;
            }
            return filedDataType;
        }
        private string GetFieldDataType_MySql(string dataType)
        {
            string filedDataType = null;
            switch (dataType)
            {
                case enumDataType.CHAR:
                case enumDataType.CLOB:
                case enumDataType.LONG:
                case enumDataType.NCHAR:
                case enumDataType.NVARCHAR:
                case enumDataType.VARCHAR:
                    filedDataType = "string";
                    break;
                case enumDataType.DATE:
                case enumDataType.DATETIME:
                case enumDataType.TIMESTAMP:
                    filedDataType = "DateTime?";
                    break;
                case enumDataType.INT:
                    filedDataType = "int?";
                    break;
                case enumDataType.FLOAT:
                case enumDataType.DOUBLE:
                case enumDataType.DECIMAL:
                case enumDataType.NUMBER:
                    filedDataType = "decimal?";
                    break;
                case enumDataType.RAW:
                    filedDataType = "byte[]";
                    break;
                default:
                    filedDataType = "string";
                    break;
            }
            return filedDataType;
        }
        /// <summary>
        /// 字段名称处理
        /// </summary>
        /// <param name="columnName">列名称</param>
        /// <returns></returns>
        private string ColumnNameHandle(string columnName)
        {
            if (string.IsNullOrWhiteSpace(columnName))
                return "";
            return columnName.ToUpper();
            //string fieldName = null;
            //string[] tempArray = columnName.Split('_');
            //if (tempArray.Length < 2)
            //{
            //    fieldName = columnName.ToLower();
            //    return fieldName;
            //}
            //string tempInfo = null;
            //for (int i = 0; i < tempArray.Length; i++)
            //{
            //    if (string.IsNullOrWhiteSpace(tempArray[i]))
            //        continue;
            //    tempInfo = tempArray[i].Trim();
            //    if (tempInfo.Length == 1)
            //    {
            //        fieldName += tempInfo.ToUpper();
            //        continue;
            //    }
            //    fieldName += tempInfo.Substring(0, 1).ToUpper() + tempInfo.Substring(1).ToLower();
            //}
            //return fieldName;
        }
        private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                IEnumerable<TableInfo> entityList = gridMain.DataSource as IEnumerable<TableInfo>;
                if (entityList == null || entityList.Count() < 1)
                {
                    return;
                }
                foreach (var item in entityList)
                {
                    item.IsChoice = chkSelectAll.Checked;
                }
                gridMain.Refresh();
            }
            catch (Exception ex)
            {
                Log.WriteLog(ex);
                WriteNotice(lblNoticeInfo, ex.Message);
            }
        }
        public delegate void dProgressBarUpdate(long total, long current);
        /// <summary>
        /// 更新进度条
        /// </summary>
        /// <param name="total"></param>
        /// <param name="current"></param>
        void ProgressBarUpdate(long total, long current)
        {
            if (this.InvokeRequired)
            {
                dProgressBarUpdate dp = new dProgressBarUpdate(ProgressBarUpdate);
                this.Invoke(dp,new object[] { total , current });
            }
            else
            {
                this.progressBar1.Maximum = (int)total;
                this.progressBar1.Value = (int)current;
            }
        }
        public delegate void dWriteNotice(Label aimLable, string info);
        private void WriteNotice(Label aimLable, string info)
        {
            if (this.InvokeRequired)
            {
                dWriteNotice dw = new dWriteNotice(WriteNotice);
                this.Invoke(dw, new object[] { aimLable, info });
            }
            else
            {
                aimLable.Text = info;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            UpdateDatabase aimForm = new UpdateDatabase();
            aimForm.ShowDialog();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string connecvtType = dropConnections.SelectedItem.ToString();
            switch(connecvtType)
            {
                case "oracle":
                    IOperate.ConnectionType = Model.enumConnectionType.Oracle;
                    break;
                case "sqlServer":
                    IOperate.ConnectionType = Model.enumConnectionType.SqlServer;
                    break;
                case "MySql":
                    IOperate.ConnectionType = Model.enumConnectionType.MySql;
                    break;
            }
            operate = IOperate.GetOperate();
        }

        private void dropConnections_SelectedIndexChanged(object sender, EventArgs e)
        {
            button2_Click(null,null);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            GYDTJ_DYY_PDM_Handler aimForm = new GYDTJ_DYY_PDM_Handler();
            aimForm.ShowDialog();
        }
    }
}
